package com.fingard.dsp.bank.directbank.cmbc01;

import com.fingard.FGBiz;
import com.fingard.constant.Format;
import com.fingard.db.JDBCHelper;
import com.fingard.dsp.bank.directbank.bankInterface.IBalance;
import com.fingard.dsp.bank.reqrespobj.balance.Req7505HisBalQry;
import com.fingard.dsp.bank.reqrespobj.balance.Req7506BalQry;
import com.fingard.dsp.bank.reqrespobj.balance.RetAts7505HisBalQry;
import com.fingard.dsp.bank.reqrespobj.balance.RetAts7506BalQry;
import com.fingard.dsp.bank.reqrespobj.balance.detail.Req7506Detail;
import com.fingard.dsp.bank.reqrespobj.balance.detail.RetAtsBalDetail;
import com.fingard.dsp.bank.reqrespobj.balance.detail.RetAtsHisBalDetail;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;
import org.springframework.stereotype.Component;

import java.sql.Connection;
import java.util.*;
@Component("CMBC01Balance")
public class CMBC01Balance extends CMBC01Base implements IBalance {
    private static final String SELECTRECEIPT = "SELECT RESERVE1,RESERVE2 FROM REQSEQIDMAPPING WHERE OUTREQSEQID=? AND BANKCODE=?;";

    //单个余额查询和批量余额查询，统一采用流处理方式
    //1、循环调用Req7506BalQry.readRecord()读取一个请求明细，然后写入发银行的XML对象
    //2、发银行
    //3、循环调用XmlTextReader.read()读取一个银行返回节点，赋值返回ATS的明细对象，
    //   然后调用RetAts7506BalQry.writeRetDetail()，写入返回ATS的明细

    public RetAts7506BalQry d_7506_BalQry(Req7506BalQry p_req7506) throws Exception {
        //先读取所有节点明细(可能有的账户是全球账户有的是普通账户)，将全球账户和普通账户区分开走不同的接口（普通余额接口支持多个账户组装报文发送一次请求给银行，
        // 全球现金池余额查询接口只能一个账户就发送一次请求给银行）,然后再组装一起返回给ATS
        RetAts7506BalQry retAts = new RetAts7506BalQry(p_req7506.reqHeader);
        retAts.writeStart();//写返回ATS的统一头部信息
        if (p_req7506.detailCount == 0) {
            retAts.writeRespCode("-1");
            retAts.writeRespInfo("查询账户数不可为0！");
            retAts.writeEnd();
            return retAts;
        }
        List<Req7506Detail> ordinaryBalQryList = new ArrayList<Req7506Detail>();//存普通账户
        List<Req7506Detail> cashPoolBalQryList = new ArrayList<Req7506Detail>();//存全球现金池账户
        List<Req7506Detail> virtualBalQryList = new ArrayList<Req7506Detail>();//存虚拟账户

        while (p_req7506.readRecord()) {
            Req7506Detail detail = p_req7506.readedDetail;
            if (p_req7506.readedDetail.actBankType.equals("11")) {//是否全球现金池账户
                //是
                cashPoolBalQryList.add(detail);
            } else if(p_req7506.readedDetail.actBankType.equals("14")){
                virtualBalQryList.add(detail);
            }else {//否
                ordinaryBalQryList.add(detail);
            }
        }
        List<RetAtsBalDetail> cashPoolRetAtsBalDetailList = new ArrayList<RetAtsBalDetail>();
        List<RetAtsBalDetail> ordinaryRetAtsBalDetailList = new ArrayList<RetAtsBalDetail>();
        List<RetAtsBalDetail> virtualRetAtsBalDetailList = new ArrayList<RetAtsBalDetail>();
        if (ordinaryBalQryList.size() != 0) {
            ordinaryRetAtsBalDetailList = d_7506_ordinaryBalQry(ordinaryBalQryList);
        }
        if (cashPoolBalQryList.size() != 0) {
            cashPoolRetAtsBalDetailList = d_7506_cashPoolBalQry(cashPoolBalQryList, p_req7506.reqHeader.bankCode);
        }
        if (virtualBalQryList.size() != 0) {
            virtualRetAtsBalDetailList = d_7506_virtualBalQry(virtualBalQryList);
        }
        for (int i = 0; i < ordinaryRetAtsBalDetailList.size(); i++) {
            retAts.writeRetDetail(ordinaryRetAtsBalDetailList.get(i), p_req7506.isBatch);
        }
        for (int i = 0; i < cashPoolRetAtsBalDetailList.size(); i++) {
            retAts.writeRetDetail(cashPoolRetAtsBalDetailList.get(i), p_req7506.isBatch);
        }
        for (int i = 0; i < virtualRetAtsBalDetailList.size(); i++) {
            retAts.writeRetDetail(virtualRetAtsBalDetailList.get(i), p_req7506.isBatch);
        }
        retAts.writeEnd();
        return retAts;
    }

    //虚拟子账户余额查询接口
    public List<RetAtsBalDetail> d_7506_virtualBalQry(List<Req7506Detail> virtualBalQryList) throws Exception {
        List<RetAtsBalDetail> virtualRetAtsBalDetailList = new ArrayList<RetAtsBalDetail>();
        for (int i = 0; i < virtualBalQryList.size(); i++) {
            RetAtsBalDetail tmpRetDetail = new RetAtsBalDetail();
            Connection conn = FGBiz.getLocalDbConn();
            try {
                //赋值通用参数
                CMBC01Header bankHeader = new CMBC01Header();
                bankHeader.trnCode = "B2EVirtualAcctQry";
                XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
                //写入通用的头部节点
                writeCommonHeader(xmlWriter, bankHeader);
                xmlWriter.writeStartElement("xDataBody");
                String qryTransId=getQryTransID();
                xmlWriter.writeElementString("trnId", qryTransId);
                xmlWriter.writeElementString("cltcookie", "",true);//客户端cookie，响应时原值返回
                xmlWriter.writeElementString("insId",qryTransId);//指令id
                xmlWriter.writeElementString("AcNo", virtualBalQryList.get(i).higherLevelAct);//实体账号
                xmlWriter.writeElementString("VirtualAcNo", virtualBalQryList.get(i).actNum);//虚拟账号
                xmlWriter.writeEndDocument();
                String[] tmpStrRet = sendToBank(xmlWriter.toXmlString());
                if (tmpStrRet[0].length() == 0) {
                    StringBuilder tmpSbMsg = new StringBuilder();
                    XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                    if (tmpBkReader != null) {
                        String tmpRetCode = tmpBkReader.getFirstText("/CMBC/responseHeader/status/code");
                        String tmpRetMessage = tmpBkReader.getFirstText("/CMBC/responseHeader/status/message");
                        if ("0".equals(tmpRetCode)) {
                            while (tmpBkReader.read("/CMBC/xDataBody/List/Map")){
                                String acNo=tmpBkReader.readedXElement.getSingleTextNotNull("VirtualAcNo");
                                if(acNo.contains("-")){
                                    String[] virtual=acNo.split("-");
                                    if(virtual.length==2){
                                        acNo=virtual[1];
                                    }
                                }
                                if(acNo.equals(virtualBalQryList.get(i).actNum)){
                                    tmpRetDetail.respCode = "0";
                                    tmpRetDetail.respInfo = tmpRetMessage;
                                    tmpRetDetail.actNum = acNo;//账号
                                    tmpRetDetail.actCur = convertCurToATS(tmpBkReader.readedXElement.getSingleTextNotNull("Currency"));//币种代码
                                    tmpRetDetail.currBal = tmpBkReader.readedXElement.getSingleTextNotNull("SelfBalance");//账号余额
                                }
                            }
                        } else {
                            tmpRetDetail.respCode = "-1";
                            tmpRetDetail.respInfo = tmpRetMessage;
                            tmpRetDetail.actNum = virtualBalQryList.get(i).actNum;
                        }
                    } else {
                        tmpRetDetail.respCode = "-1";
                        tmpRetDetail.respInfo = tmpSbMsg.toString();
                        tmpRetDetail.actNum = virtualBalQryList.get(i).actNum;
                    }
                } else {
                    tmpRetDetail.respCode = "-1";
                    tmpRetDetail.respInfo = tmpStrRet[1];
                    tmpRetDetail.actNum = virtualBalQryList.get(i).actNum;
                }
            } catch (Exception e) {
                tmpRetDetail.respCode = "-1";
                tmpRetDetail.respInfo = "虚拟账号查询余额异常！";
                e.printStackTrace();
                WriteBankLogLn("虚拟账号查询余额异常，异常信息：" + e.getMessage());
            } finally {
                conn.close();
            }
            virtualRetAtsBalDetailList.add(tmpRetDetail);
        }
        return virtualRetAtsBalDetailList;
    }

    //全球现金池账户余额查询接口
    public List<RetAtsBalDetail> d_7506_cashPoolBalQry(List<Req7506Detail> cashPoolBalQryList, String bankCode) throws Exception {
        List<RetAtsBalDetail> cashPoolRetAtsBalDetailList = new ArrayList<RetAtsBalDetail>();
        for (int i = 0; i < cashPoolBalQryList.size(); i++) {
            RetAtsBalDetail tmpRetDetail = new RetAtsBalDetail();
            Connection conn = FGBiz.getLocalDbConn();
            try {
                //赋值通用参数
                CMBC01Header bankHeader = new CMBC01Header();
                bankHeader.trnCode = "CBCashPoolAccBalanceQry";
                XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
                //写入通用的头部节点
                writeCommonHeader(xmlWriter, bankHeader);

                xmlWriter.writeStartElement("xDataBody");
                xmlWriter.writeElementString("trnId", Format.DateTime17Format.format(new Date()));
                xmlWriter.writeElementString("accountId", cashPoolBalQryList.get(i).accountId);//帐号 ID
                xmlWriter.writeElementString("account", cashPoolBalQryList.get(i).actNum);
                Map<String, Object> map = JDBCHelper.execQuerySingle(conn, SELECTRECEIPT, new Object[]{cashPoolBalQryList.get(i).accountId, bankCode});
                if (map.size() == 0) {
                    tmpRetDetail.respCode = "-1";
                    tmpRetDetail.respInfo = "账号：" + cashPoolBalQryList.get(i).actNum + ",数据库没有是否民生银行标志及账号类型映射！";
                    cashPoolRetAtsBalDetailList.add(tmpRetDetail);
                    continue;
                }
                xmlWriter.writeElementString("isCmbc", map.get("RESERVE1").toString());//是否民生银行标志0-他行账户 1-民生银行账户
                xmlWriter.writeElementString("accountType", map.get("RESERVE2").toString());//1-境内分行账户；2-境外分行账户；3-他行账户
                xmlWriter.writeEndDocument();

                String[] tmpStrRet = sendToBank(xmlWriter.toXmlString());
                if (tmpStrRet[0].length() == 0) {
                    StringBuilder tmpSbMsg = new StringBuilder();
                    XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                    if (tmpBkReader != null) {
                        String tmpRetCode = tmpBkReader.getFirstText("/CMBC/responseHeader/status/code");
                        String tmpRetMessage = tmpBkReader.getFirstText("/CMBC/responseHeader/status/message");
                        if (tmpRetCode.equals("0")) {
                            tmpRetDetail.respCode = "0";
                            tmpRetDetail.respInfo = "全球账号：" + cashPoolBalQryList.get(i).actNum + "余额查询成功！";
                            tmpRetDetail.custName = tmpBkReader.getFirstText("/CMBC/xDataBody/List/Map/custName");//客户名称
                            tmpRetDetail.actNum = tmpBkReader.getFirstText("/CMBC/xDataBody/List/Map/account");//账号
                            tmpRetDetail.actCur = convertCurToATS(tmpBkReader.getFirstText("/CMBC/xDataBody/List/Map/currencyCode"));//币种代码
                            tmpRetDetail.actCurName = tmpBkReader.getFirstText("/CMBC/xDataBody/List/Map/currencyName");//币种名称
                            tmpRetDetail.currBal = tmpBkReader.getFirstText("/CMBC/xDataBody/List/Map/balance");//账号余额
                            tmpRetDetail.availBal = tmpBkReader.getFirstText("/CMBC/xDataBody/List/Map/availBalance");//可用余额
                            tmpRetDetail.bankName = tmpBkReader.getFirstText("/CMBC/xDataBody/List/Map/bankName");//开户银行
                            if (map.get("RESERVE2").toString().equals("3")) {///同行（1-境内分行账户；2-境外分行账户）；他行：3-他行账户
                                tmpRetDetail.lastTranDate = tmpBkReader.getFirstText("/CMBC/xDataBody/List/Map/verifyDate");//对账日期(跨行时候返回)
                                tmpRetDetail.countryName = tmpBkReader.getFirstText("/CMBC/xDataBody/List/Map/countryName");//开户行所在国家/地区（他行余额返回）
                            } else {
                                tmpRetDetail.acState = tmpBkReader.getFirstText("/CMBC/xDataBody/List/Map/acState");//账户状态 0-新建，2-正常，3-注销（本行余额返回）
                            }
                        } else {
                            tmpRetDetail.respCode = "-1";
                            tmpRetDetail.respInfo = tmpRetMessage;
                            tmpRetDetail.actNum = cashPoolBalQryList.get(i).actNum;
                        }
                    } else {
                        tmpRetDetail.respCode = "-1";
                        tmpRetDetail.respInfo = tmpSbMsg.toString();
                        tmpRetDetail.actNum = cashPoolBalQryList.get(i).actNum;
                    }
                } else {
                    tmpRetDetail.respCode = "-1";
                    tmpRetDetail.respInfo = tmpStrRet[1];
                    tmpRetDetail.actNum = cashPoolBalQryList.get(i).actNum;
                }
            } catch (Exception e) {
                tmpRetDetail.respCode = "-1";
                tmpRetDetail.respInfo = "全球现金池账号查询余额异常！";
                e.printStackTrace();
                WriteBankLogLn("全球现金池账号查询余额异常，异常信息：" + e.getMessage());
            } finally {
                conn.close();
            }
            cashPoolRetAtsBalDetailList.add(tmpRetDetail);
        }
        return cashPoolRetAtsBalDetailList;
    }

    //普通账户余额查询接口
    public List<RetAtsBalDetail> d_7506_ordinaryBalQry(List<Req7506Detail> ordinaryBalQryList) throws Exception {//余额查询
        //同一个客户号的企业同一个账号不能在设定的时间内连续查询，目前设置是15分钟
        //余额查询返回ATS的对象
//        RetAts7506BalQry retAts = new RetAts7506BalQry(p_req7506.reqHeader);
//        retAts.writeStart();//写返回ATS的统一头部信息
        List<RetAtsBalDetail> ordinaryRetAtsBalDetailList = new ArrayList<RetAtsBalDetail>();
        String RespCode = "0";
        String RespInfo = "";

        try {
            //赋值通用参数
            CMBC01Header bankHeader = new CMBC01Header();
            bankHeader.trnCode = "qryBalNew";
            XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
            //写入通用的头部节点
            writeCommonHeader(xmlWriter, bankHeader);
            xmlWriter.writeStartElement("xDataBody");
            xmlWriter.writeElementString("trnId", Format.DateTime17Format.format(new Date()));
            xmlWriter.writeStartElement("acntList");
            for (int i = 0; i < ordinaryBalQryList.size(); i++) {
                xmlWriter.writeElementString("acntNo", ordinaryBalQryList.get(i).actNum);
            }
//            while (p_req7506.readRecord()) {
//                //仅支持人民币
//                xmlWriter.writeElementString("acntNo", p_req7506.readedDetail.actNum);
//
//            }
            xmlWriter.writeEndElement();
            xmlWriter.writeEndDocument();


            String[] tmpStrRet = sendToBank(xmlWriter.toXmlString());
            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String tmpRetCode = tmpBkReader.getFirstText("/CMBC/responseHeader/status/code");
                    String tmpRetMessage = tmpBkReader.getFirstText("/CMBC/responseHeader/status/message");
                    if (tmpRetCode.equals("0")) {
                        RespCode = "0";
                        while (tmpBkReader.read("/CMBC/xDataBody/balList/balInfo")) {
                            RetAtsBalDetail tmpRetDetail = new RetAtsBalDetail();
                            if (tmpBkReader.readedXElement.getSingleText("state").equals("1")) {
                                tmpRetDetail.respCode = "0";
                                //tmpRetDetail.actCur = convertCurToATS(tmpBkReader.readedXElement.getSingleText("CurrType"));
                                tmpRetDetail.actNum = tmpBkReader.readedXElement.getSingleText("acntNo");
                                tmpRetDetail.currBal = tmpBkReader.readedXElement.getSingleText("acctBal");
                                tmpRetDetail.availBal = tmpBkReader.readedXElement.getSingleText("avlBal");
                                tmpRetDetail.frozenBal = tmpBkReader.readedXElement.getSingleText("frzBal");
                            } else {
                                tmpRetDetail.respCode = "-1";
                                tmpRetDetail.respInfo = tmpBkReader.readedXElement.getSingleText("errCode") + "-" + tmpBkReader.readedXElement.getSingleText("errMsg");
                            }
//                            retAts.writeRetDetail(tmpRetDetail, p_req7506.isBatch);
                            ordinaryRetAtsBalDetailList.add(tmpRetDetail);
                        }
                    } else {
                        RespCode = "-1";
                        RespInfo = tmpRetMessage;
//                        retAts.writeRespCode("-1");
//                        retAts.writeRespInfo(tmpRetMessage);
                    }
                } else {
                    RespCode = "-1";
                    RespInfo = tmpSbMsg.toString();
//                    retAts.writeRespCode("-1");
//                    retAts.writeRespInfo(tmpSbMsg.toString());
                }
            } else {
                RespCode = "-1";
                RespInfo = tmpStrRet[1];
//                retAts.writeRespCode("-1");
//                retAts.writeRespInfo(tmpStrRet[1]);
            }
        } catch (Exception e) {
            RespCode = "-1";
            RespInfo = "普通账号余额查询异常！";
//            retAts.writeRespCode("-1");
//            retAts.writeRespInfo(e.getMessage());
            e.printStackTrace();
            WriteBankLogLn("普通账号余额查询异常！异常信息：" + e.getMessage());
        }
        if (RespCode.equals("-1")) {
            for (int i = 0; i < ordinaryBalQryList.size(); i++) {
                RetAtsBalDetail tmpRetDetail = new RetAtsBalDetail();
                tmpRetDetail.respCode = "-1";
                tmpRetDetail.respInfo = RespInfo;
                ordinaryRetAtsBalDetailList.add(tmpRetDetail);
            }
        }
//        retAts.writeEnd();
//        return retAts;
        return ordinaryRetAtsBalDetailList;
    }

    @Override
    public RetAts7505HisBalQry d_7505_BalQry(Req7505HisBalQry p_req7505) throws Exception {
        RetAts7505HisBalQry retAts = new RetAts7505HisBalQry(p_req7505.reqHeader);
        retAts.writeStart();
        StringBuilder messageStr = new StringBuilder();
        List<RetAtsHisBalDetail> retAtsHisBalDetailList =new ArrayList<RetAtsHisBalDetail>();
        try {
            //赋值通用参数
            CMBC01Header bankHeader = new CMBC01Header();
            bankHeader.trnCode = "qryHistoryBal";

            Calendar tmpCalendarFrom = Calendar.getInstance();
            tmpCalendarFrom.setTime(p_req7505.getDateFrom());
            Calendar tmpCalendarTo = Calendar.getInstance();
            tmpCalendarTo.setTime(p_req7505.getDateTo());
            while (tmpCalendarTo.compareTo(tmpCalendarFrom) != -1) {
                XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
                try {
                    //写入通用的头部节点
                    writeCommonHeader(xmlWriter, bankHeader);
                    //开始拼接请求报文体
                    xmlWriter.writeStartElement("xDataBody");
                    xmlWriter.writeElementString("trnId", Format.DateTime17Format.format(new Date()));
                    xmlWriter.writeElementString("cltcookie", "");
                    xmlWriter.writeElementString("acntNo", p_req7505.actNum);
                    xmlWriter.writeElementString("qryDate", Format.Date10Format.format(tmpCalendarFrom.getTime()));
                    xmlWriter.writeEndElement();
                    xmlWriter.writeEndElement();
                    String[] tmpStrRet = sendToBank(xmlWriter.toXmlString(), false, p_req7505.reqHeader.transType, p_req7505.reqHeader.transType);
                    if (tmpStrRet[0].length() == 0) {
                        StringBuilder tmpSbMsg = new StringBuilder();
                        XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                        if (tmpBkReader != null) {
                            String tmpRetCode = tmpBkReader.getFirstText("/CMBC/responseHeader/status/code");
                            String tmpRetMessage = tmpBkReader.getFirstText("/CMBC/responseHeader/status/message");
                            if (tmpRetCode.equals("0")) {
                                while (tmpBkReader.read("/CMBC/xDataBody")) {
                                    RetAtsHisBalDetail tmpRetAtsHisBalDetail = new RetAtsHisBalDetail();
                                    tmpRetAtsHisBalDetail.actBal = tmpBkReader.readedXElement.getSingleText("balance");
                                    tmpRetAtsHisBalDetail.balDate = Format.Date10Format.format(tmpCalendarFrom.getTime());
                                    retAtsHisBalDetailList.add(tmpRetAtsHisBalDetail);
                                }
                            } else {
                                messageStr.append(Format.Date10Format.format(tmpCalendarFrom.getTime())).append(":").append(tmpRetMessage).append(";");
                            }
                        } else {
                            messageStr.append(Format.Date10Format.format(tmpCalendarFrom.getTime())).append(":").append(tmpSbMsg).append(";");
                        }
                    } else {
                        messageStr.append(Format.Date10Format.format(tmpCalendarFrom.getTime())).append(":").append(tmpStrRet[1]).append(";");
                    }
                    tmpCalendarFrom.add(Calendar.DAY_OF_MONTH, 1);
                } catch (Exception e) {
                    messageStr.append(Format.Date10Format.format(tmpCalendarFrom.getTime())).append(":").append(e.getMessage()).append(";");
                }
            }
            if (retAtsHisBalDetailList.size() > 0) {
                retAts.writeRespCode("0");
                if (messageStr.toString().length() > 0) {
                    retAts.writeRespInfo(messageStr.toString());
                }
                for (RetAtsHisBalDetail tmpRetAtsHisBalDetail : retAtsHisBalDetailList) {
                    retAts.writeRetDetail(tmpRetAtsHisBalDetail);
                }
            } else {
                retAts.writeRespCode("-1");
                retAts.writeRespInfo(messageStr.toString());
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            retAts.writeRespCode("-1");
            retAts.writeRespInfo(ex.getMessage());
            WriteBankLogLn(ex);
        } finally {
            retAts.writeEnd();
        }
        return retAts;
    }
}
